home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / pvm34b3.zip / pvm34b3 / pvm3 / tracer / trcsort.c < prev    next >
C/C++ Source or Header  |  1997-07-22  |  17KB  |  1,122 lines

  1.  
  2. static char rcsid[] =
  3.     "$Id: trcsort.c,v 4.9 1997/06/17 22:00:41 pvmsrc Exp $";
  4.  
  5. /*
  6.  *         Trcsort version 1.0:  A Trace File Sorter for PVM
  7.  *           Oak Ridge National Laboratory, Oak Ridge TN.
  8.  *           Authors:  James Arthur Kohl and G. A. Geist
  9.  *                   (C) 1994 All Rights Reserved
  10.  *
  11.  *                              NOTICE
  12.  *
  13.  * Permission to use, copy, modify, and distribute this software and
  14.  * its documentation for any purpose and without fee is hereby granted
  15.  * provided that the above copyright notice appear in all copies and
  16.  * that both the copyright notice and this permission notice appear
  17.  * in supporting documentation.
  18.  *
  19.  * Neither the Institution, Oak Ridge National Laboratory, nor the
  20.  * Authors make any representations about the suitability of this
  21.  * software for any purpose.  This software is provided ``as is''
  22.  * without express or implied warranty.
  23.  *
  24.  * Tracer was funded by the U.S. Department of Energy.
  25.  */
  26.  
  27.  
  28. /* Tracer Headers */
  29.  
  30. #include <stdio.h>
  31. #include <sys/types.h>
  32. #include <sys/stat.h>
  33.  
  34. #include <pvm3.h>
  35. #include <pvmtev.h>
  36.  
  37. #include "trcdef.h"
  38.  
  39.  
  40. /* Constants */
  41.  
  42. #define HANDLE_HOST_SYNC    1
  43.  
  44. #define MAX_OPEN_FP    10
  45.  
  46.  
  47. /* Macros */
  48.  
  49. #define TIME_COMPARE( _t1, _t2 ) \
  50. ( \
  51.     ( (_t1).tv_sec > (_t2).tv_sec \
  52.             || ( (_t1).tv_sec == (_t2).tv_sec \
  53.                 && (_t1).tv_usec > (_t2).tv_usec ) ) ? 1 : \
  54.         ( ( (_t1).tv_sec == (_t2).tv_sec \
  55.             && (_t1).tv_usec == (_t2).tv_usec ) ? 0 : -1 ) \
  56. ) \
  57. \
  58.  
  59.  
  60. /* Data Structures */
  61.  
  62. struct fp_buffer_struct
  63. {
  64.     FILE *fp;
  65.     char *rwstr;
  66.     /* TMPFILE */ struct tmpfile_struct *tmpfile;
  67.     /* FPBUF */ struct fp_buffer_struct *next;
  68. };
  69.  
  70. typedef struct fp_buffer_struct *FPBUF;
  71.  
  72.  
  73. struct tmpfile_struct
  74. {
  75.     FPBUF fpbuf;
  76.     char *fname;
  77.     long lastseek;
  78.     TRC_TEVDESC savetd;
  79.     TRC_TEVREC savetr;
  80.     int tid;
  81.     struct timeval nexttime;
  82.     struct timeval lasttime;
  83.     struct timeval delta;
  84.     int valid;
  85.     int eof;
  86.     /* TMPFILE */ struct tmpfile_struct *next;
  87. };
  88.  
  89. typedef struct tmpfile_struct *TMPFILE;
  90.  
  91.  
  92. /* Handler Routines */
  93.  
  94. TRC_TEVREC save_tevrec();
  95.  
  96. TMPFILE create_tmpfile();
  97. TMPFILE get_tmpfile();
  98.  
  99. FPBUF create_fpbuf();
  100.  
  101. void get_tevrec_tmpfile();
  102. void handle_event_split();
  103. void handle_event_join();
  104. void handle_passthru();
  105. void my_status_msg();
  106. void program_init();
  107. void free_fpbuf();
  108. void read_args();
  109. void sync_time();
  110. void close_fp();
  111. void trc_init();
  112. void cleanup();
  113. void usage();
  114. void bail();
  115.  
  116. int verify_fp();
  117.  
  118.  
  119. /* Globals */
  120.  
  121. TMPFILE CURRENTTF;
  122. TMPFILE    LASTTF;
  123. TMPFILE    TMPF;
  124.  
  125. FPBUF    FPS;
  126. int        NFPS;
  127.  
  128. TRC_ID    ID;
  129.  
  130. char    DIRNAME[255];
  131.  
  132. char    *TRACE_OUTFILE;
  133. char    *TRACE_INFILE;
  134. char    *OUTPUT_FILE;
  135.  
  136. int        vflag;
  137.  
  138.  
  139. /* MAIN */
  140.  
  141. int
  142. main( argc, argv )
  143. int argc;
  144. char **argv;
  145. {
  146.     TMPFILE NEXTTF;
  147.     TMPFILE HOSTTF;
  148.     TMPFILE TF;
  149.  
  150.     static struct timeval tmpt = { -1, -1 };
  151.  
  152.     int host;
  153.     int done;
  154.     int eof;
  155.  
  156.     /* Read Command Line Args */
  157.  
  158.     read_args( argc, argv );
  159.  
  160.     /* Initialize Program Constants & Structs */
  161.  
  162.     program_init();
  163.  
  164.     /* Initialize Tracer Globals */
  165.  
  166.     trc_init();
  167.  
  168.     /* Parse Input Trace, Create Subfiles */
  169.  
  170.     while ( trc_read_trace_event( ID, &eof ) );
  171.  
  172.     fclose( ID->trace_in );
  173.  
  174.     /* Flush Temporary File Ptrs, Reset Subfiles for Reading */
  175.  
  176.     TF = TMPF;
  177.  
  178.     while ( TF != NULL )
  179.     {
  180.         close_fp( TF );
  181.  
  182.         TF->eof = TRC_FALSE;
  183.  
  184.         TF = TF->next;
  185.     }
  186.  
  187.     /* Reset Pass Thru -> All Goes to Output Trace Now */
  188.  
  189.     LASTTF = (TMPFILE) NULL;
  190.  
  191.     /* Set Event Handling for Joining */
  192.  
  193.     ID->handle_event = handle_event_join;
  194.  
  195.     /* Read In First Event From Each Subfile (Prime Pump) */
  196.  
  197.     TF = TMPF;
  198.  
  199.     while ( TF != NULL )
  200.     {
  201.         /* Check Setting of Time Stamp Delta */
  202.  
  203.         host = pvm_tidtohost( TF->tid );
  204.  
  205.         if ( host != TF->tid )
  206.         {
  207.             HOSTTF = get_tmpfile( host, &tmpt, TRC_FALSE );
  208.  
  209.             if ( HOSTTF != NULL )
  210.             {
  211.                 TF->delta.tv_sec = HOSTTF->delta.tv_sec;
  212.                 TF->delta.tv_usec = HOSTTF->delta.tv_usec;
  213.             }
  214.         }
  215.  
  216.         /* Get First Event (Record) */
  217.  
  218.         TF->valid = TRC_FALSE;
  219.  
  220.         do
  221.         {
  222.             get_tevrec_tmpfile( TF );
  223.         }
  224.         while( !(TF->valid) && !(TF->eof) );
  225.  
  226.         if ( TF->eof )
  227.             close_fp( TF );
  228.  
  229.         TF = TF->next;
  230.     }
  231.  
  232.     /* Read In Subfiles, Dump Sorted Trace */
  233.  
  234.     do
  235.     {
  236.         done = TRC_TRUE;
  237.  
  238.         /* Find "Next" Trace Event */
  239.  
  240.         NEXTTF = (TMPFILE) NULL;
  241.  
  242.         TF = TMPF;
  243.  
  244.         while ( TF != NULL )
  245.         {
  246.             if ( TF->valid )
  247.             {
  248.                 if ( NEXTTF != NULL )
  249.                 {
  250.                     if ( TIME_COMPARE( TF->nexttime,
  251.                             NEXTTF->nexttime ) < 0
  252.                         || ( TIME_COMPARE( TF->nexttime,
  253.                                 NEXTTF->nexttime ) == 0
  254.                             && TF->tid < NEXTTF->tid ) )
  255.                     {
  256.                         NEXTTF = TF;
  257.                     }
  258.                 }
  259.  
  260.                 else
  261.                     NEXTTF = TF;
  262.  
  263.                 done = TRC_FALSE;
  264.             }
  265.  
  266.             TF = TF->next;
  267.         }
  268.  
  269.         /* Dump It */
  270.  
  271.         if ( NEXTTF != NULL )
  272.         {
  273.             trc_store_tevrec( ID, NEXTTF->savetd, NEXTTF->savetr,
  274.                     NEXTTF->tid );
  275.  
  276.             /* Get Next Event for Task */
  277.  
  278.             NEXTTF->valid = TRC_FALSE;
  279.  
  280.             do
  281.             {
  282.                 get_tevrec_tmpfile( NEXTTF );
  283.             }
  284.             while( !(NEXTTF->valid) && !(NEXTTF->eof) );
  285.  
  286.             if ( NEXTTF->eof )
  287.                 close_fp( NEXTTF );
  288.         }
  289.     }
  290.     while ( !done );
  291.  
  292.     fclose( ID->trace_out );
  293.  
  294.     cleanup();
  295.  
  296.     exit( 0 );
  297. }
  298.  
  299.  
  300. void
  301. handle_event_split( trcid, TD, TR )
  302. TRC_ID trcid;
  303. TRC_TEVDESC TD;
  304. TRC_TEVREC TR;
  305. {
  306.     TMPFILE TFptr;
  307.     TMPFILE TF;
  308.  
  309.     FILE *fpsave;
  310.  
  311.     struct timeval tmpt;
  312.  
  313.     int tid;
  314.  
  315.     if ( trcid != ID )
  316.     {
  317.         printf( "Error: Unknown Trace ID\n" );
  318.  
  319.         return;
  320.     }
  321.  
  322.     /* Grab Task ID from Event */
  323.  
  324.     tid = TRC_GET_TEVREC_VALUE( TR, "TID", int );
  325.  
  326.     tmpt.tv_sec = TRC_GET_TEVREC_VALUE( TR, "TS", int );
  327.     tmpt.tv_usec = TRC_GET_TEVREC_VALUE( TR, "TU", int );
  328.  
  329.     /* Key Off of TID & Time Stamp to Select Temp File */
  330.  
  331.     TF = get_tmpfile( tid, &tmpt, TRC_TRUE );
  332.  
  333.     if ( TF == NULL )
  334.     {
  335.         printf( "\nError Creating Temporary Trace File\n\n" );
  336.         bail();
  337.     }
  338.  
  339.     /* Set Time Stamp Marker */
  340.  
  341.     TF->lasttime.tv_sec = tmpt.tv_sec;
  342.     TF->lasttime.tv_usec = tmpt.tv_usec;
  343.  
  344.     /* Check for Host Sync */
  345.  
  346.     if ( TD->hid == HANDLE_HOST_SYNC )
  347.     {
  348.         TF->delta.tv_sec = TRC_GET_TEVREC_VALUE( TR, "HDS", int );
  349.         TF->delta.tv_usec = TRC_GET_TEVREC_VALUE( TR, "HDU", int );
  350.  
  351.         TFptr = TMPF;
  352.  
  353.         while ( TFptr != NULL )
  354.         {
  355.             if ( TFptr->tid == TF->tid && TFptr != TF )
  356.             {
  357.                 TFptr->delta.tv_sec = TF->delta.tv_sec;
  358.                 TFptr->delta.tv_usec = TF->delta.tv_usec;
  359.             }
  360.  
  361.             TFptr = TFptr->next;
  362.         }
  363.     }
  364.  
  365.     /* Check for Descriptor Dump */
  366.  
  367.     if ( TD->dump )
  368.         trc_dump_tevdesc( ID, TD, -1 );
  369.  
  370.     /* Write Event to Temp File */
  371.  
  372.     if ( !verify_fp( TF, "a" ) )
  373.         bail();
  374.  
  375.     fpsave = ID->trace_out;
  376.  
  377.     ID->trace_out = TF->fpbuf->fp;
  378.  
  379.     trc_store_tevrec( ID, TD, TR, tid );
  380.  
  381.     ID->trace_out = fpsave;
  382.     
  383.     /* Save Last Temp File Ptr for Pass Thru */
  384.  
  385.     LASTTF = TF;
  386. }
  387.  
  388.  
  389. void
  390. handle_event_join( trcid, TD, TR )
  391. TRC_ID trcid;
  392. TRC_TEVDESC TD;
  393. TRC_TEVREC TR;
  394. {
  395.     if ( trcid != ID )
  396.     {
  397.         printf( "Error: Unknown Trace ID\n" );
  398.  
  399.         return;
  400.     }
  401.  
  402.     if ( CURRENTTF == NULL )
  403.     {
  404.         printf( "Warning:  Current Temp File Not Set...\n" );
  405.  
  406.         return;
  407.     }
  408.  
  409.     CURRENTTF->nexttime.tv_sec = TRC_GET_TEVREC_VALUE( TR, "TS", int );
  410.     CURRENTTF->nexttime.tv_usec = TRC_GET_TEVREC_VALUE( TR, "TU", int );
  411.  
  412.     sync_time( CURRENTTF );
  413.  
  414.     CURRENTTF->savetd = TD;
  415.     CURRENTTF->savetr = save_tevrec( TR );
  416.  
  417.     CURRENTTF->valid = TRC_TRUE;
  418. }
  419.  
  420.  
  421. void
  422. handle_passthru( trcid, str )
  423. TRC_ID trcid;
  424. char *str;
  425. {
  426.     if ( trcid != ID )
  427.     {
  428.         printf( "Error: Unknown Trace ID\n" );
  429.  
  430.         return;
  431.     }
  432.  
  433.     if ( LASTTF != NULL )
  434.     {
  435.         if ( !verify_fp( LASTTF, "a" ) )
  436.             bail();
  437.  
  438.         fprintf( LASTTF->fpbuf->fp, "%s\n", str );
  439.     }
  440.     
  441.     else
  442.         fprintf( ID->trace_out, "%s\n", str );
  443. }
  444.  
  445.  
  446. void
  447. read_args( argc, argv )
  448. int argc;
  449. char **argv;
  450. {
  451.     char tmp[1024];
  452.  
  453.     int i, j, k;
  454.     int do_usage;
  455.     int len;
  456.  
  457.     TRACE_OUTFILE = (char *) NULL;
  458.     TRACE_INFILE = (char *) NULL;
  459.     OUTPUT_FILE = (char *) NULL;
  460.  
  461.     vflag = 0;
  462.  
  463.     do_usage = 0;
  464.  
  465.     for ( i=1 ; i < argc ; i++ )
  466.     {
  467.         if ( argv[i][0] == '-' )
  468.         {
  469.             k = i + 1;
  470.  
  471.             len = strlen( argv[i] );
  472.  
  473.             for ( j=0 ; j < len ; j++ )
  474.             {
  475.                 switch ( argv[i][j] )
  476.                 {
  477.                     case 'o':
  478.                     {
  479.                         if ( TRACE_OUTFILE != NULL )
  480.                             free( TRACE_OUTFILE );
  481.             
  482.                         TRACE_OUTFILE = trc_copy_str( argv[ k++ ] );
  483.  
  484.                         break;
  485.                     }
  486.  
  487.                     case 'O':
  488.                     {
  489.                         if ( OUTPUT_FILE != NULL )
  490.                             free( OUTPUT_FILE );
  491.             
  492.                         OUTPUT_FILE = trc_copy_str( argv[ k++ ] );
  493.  
  494.                         break;
  495.                     }
  496.  
  497.                     case 'H':
  498.                     case 'h':
  499.                         usage(); break;
  500.  
  501.                     case 'v': vflag++; break;
  502.  
  503.                     case '-': break;
  504.  
  505.                     default:
  506.                     {
  507.                         printf( "Unknown Option -%c\n", argv[i][j] );
  508.  
  509.                         do_usage++;
  510.  
  511.                         break;
  512.                     }
  513.                 }
  514.             }
  515.  
  516.             i = k - 1;
  517.         }
  518.  
  519.         else
  520.         {
  521.             if ( TRACE_INFILE != NULL )
  522.                 free( TRACE_INFILE );
  523.             
  524.             TRACE_INFILE = trc_copy_str( argv[i] );
  525.         }
  526.     }
  527.  
  528.     if ( do_usage )
  529.         usage();
  530. }
  531.  
  532.  
  533. void
  534. usage()
  535. {
  536.     printf( "\nusage:  trcsort [ <trace_infile> ] " );
  537.     printf( "[ -o <trace_outfile> ] " );
  538.     printf( "[ -O <output_file> ] " );
  539.     printf( "[ -v ] " );
  540.     printf( "\n\n" );
  541.  
  542.     printf( "where:\n" );
  543.     printf( "------\n" );
  544.  
  545.     printf( "<trace_infile>    =    " );
  546.     printf( "trace file to be sorted (default is stdin)\n" );
  547.  
  548.     printf( "<trace_outfile>   =    " );
  549.     printf( "file to store sorted trace (default is stdout)\n" );
  550.  
  551.     printf( "<output_file>     =    " );
  552.     printf( "file to store separate copy of any task output\n" );
  553.  
  554.     printf( "-v                =    " );
  555.     printf( "display dynamic open file usage\n" );
  556.  
  557.     printf( "\n" );
  558.  
  559.     exit( 0 );
  560. }
  561.  
  562.  
  563. void
  564. program_init()
  565. {
  566.     /* Create Temp Directory for Subfiles */
  567.  
  568.     sprintf( DIRNAME, "tmpsort.%d", (int) getpid() );
  569.  
  570.     if ( mkdir( DIRNAME, S_IRWXU | S_IRWXG | S_IRWXO ) )
  571.     {
  572.         printf( "\nError Creating Temporary Directory \"%s\".\n\n",
  573.                 DIRNAME );
  574.  
  575.         exit( -1 );
  576.     }
  577.  
  578.     /* Initialize Temporary File Ptrs */
  579.  
  580.     LASTTF = (TMPFILE) NULL;
  581.  
  582.     TMPF = (TMPFILE) NULL;
  583.  
  584.     FPS = (FPBUF) NULL;
  585.     NFPS = 0;
  586. }
  587.  
  588.  
  589. void
  590. trc_init()
  591. {
  592.     /* Initialize Tracer */
  593.  
  594.     trc_tracer_init();
  595.  
  596.     /* Get Tracer ID */
  597.  
  598.     ID = trc_get_tracer_id();
  599.  
  600.     /* Set Local Handler Routines */
  601.  
  602.     ID->handle_command = handle_passthru;
  603.     ID->handle_comment = handle_passthru;
  604.     ID->handle_event = handle_event_split;
  605.     ID->status_msg = my_status_msg;
  606.  
  607.     /* Set Up Handle ID for Host Sync Events */
  608.  
  609.     trc_add_to_trie( TRC_HANDLE_TRIE,
  610.         "host_sync",    (void *) HANDLE_HOST_SYNC );
  611.  
  612.     /* Create In & Out Trace File Ptrs */
  613.  
  614.     if ( TRACE_INFILE != NULL )
  615.     {
  616.         ID->trace_in = fopen( TRACE_INFILE, "r" );
  617.         if ( !trc_filecheck( ID->trace_in, TRACE_INFILE ) )
  618.             bail();
  619.     }
  620.  
  621.     else
  622.         ID->trace_in = stdin;
  623.  
  624.     if ( TRACE_OUTFILE != NULL )
  625.     {
  626.         ID->trace_out = fopen( TRACE_OUTFILE, "w" );
  627.         if ( !trc_filecheck( ID->trace_out, TRACE_OUTFILE ) )
  628.             bail();
  629.     }
  630.  
  631.     else
  632.         ID->trace_out = stdout;
  633.  
  634.     /* Open Additional Output File */
  635.  
  636.     if ( OUTPUT_FILE != NULL )
  637.     {
  638.         trc_set_output_file( ID, OUTPUT_FILE );
  639.  
  640.         trc_open_output_file( ID );
  641.     }
  642. }
  643.  
  644.  
  645. /* Status Message Handler */
  646.  
  647. void my_status_msg( ID, msg )
  648. TRC_ID ID;
  649. char *msg;
  650. {
  651.     printf( "%s\n", msg );
  652. }
  653.  
  654.  
  655. /* TRC_TEVREC Routines */
  656.  
  657. TRC_TEVREC
  658. save_tevrec( TR )    /* actually, more like "steal_tevrec" :-) */
  659. TRC_TEVREC TR;
  660. {
  661.     TRC_TEVREC tmp;
  662.  
  663.     tmp = trc_create_tevrec();
  664.  
  665.     tmp->ddesc = TR->ddesc;
  666.     TR->ddesc = (TRC_DATADESC) NULL;
  667.  
  668.     tmp->value = TR->value;
  669.     TR->value = (TRC_VALUE) NULL;
  670.  
  671.     tmp->num = TR->num;
  672.     TR->num = -1;
  673.  
  674.     tmp->next = TR->next;
  675.     TR->next = (TRC_TEVREC) NULL;
  676.  
  677.     return( tmp );
  678. }
  679.  
  680.  
  681. /* TMPFILE Routines */
  682.  
  683. TMPFILE
  684. create_tmpfile()
  685. {
  686.     TMPFILE tmp;
  687.  
  688.     tmp = (TMPFILE) malloc( sizeof( struct tmpfile_struct ) );
  689.     trc_memcheck( tmp, "Temporary File Structure" );
  690.  
  691.     tmp->fpbuf = (FPBUF) NULL;
  692.     tmp->fname = (char *) NULL;
  693.     tmp->lastseek = (long) 0;
  694.  
  695.     tmp->savetr = (TRC_TEVREC) NULL;
  696.     tmp->tid = -1;
  697.  
  698.     tmp->nexttime.tv_sec = -1;
  699.     tmp->nexttime.tv_usec = -1;
  700.  
  701.     tmp->lasttime.tv_sec = -1;
  702.     tmp->lasttime.tv_usec = -1;
  703.  
  704.     tmp->delta.tv_sec = 0;
  705.     tmp->delta.tv_usec = 0;
  706.  
  707.     tmp->valid = -1;
  708.     tmp->eof = -1;
  709.     tmp->next = (TMPFILE) NULL;
  710.  
  711.     return( tmp );
  712. }
  713.  
  714.  
  715. TMPFILE
  716. get_tmpfile( tid, tmptp, createflag )
  717. int tid;
  718. struct timeval *tmptp;
  719. int createflag;
  720. {
  721.     TMPFILE TF;
  722.  
  723.     static struct timeval delta = { 0, 0 };
  724.  
  725.     char fname[255];
  726.  
  727.     int index;
  728.  
  729.     TF = TMPF;
  730.  
  731.     index = 1;
  732.  
  733.     while ( TF != NULL )
  734.     {
  735.         if ( TF->tid == tid )
  736.         {
  737.             if ( ( tmptp->tv_sec == -1 && tmptp->tv_usec == -1 )
  738.                     || TIME_COMPARE( *tmptp, TF->lasttime ) >= 0 )
  739.             {
  740.                 return( TF );
  741.             }
  742.  
  743.             delta.tv_sec = TF->delta.tv_sec;
  744.             delta.tv_usec = TF->delta.tv_usec;
  745.  
  746.             index++;
  747.         }
  748.  
  749.         TF = TF->next;
  750.     }
  751.  
  752.     if ( !createflag )
  753.         return( (TMPFILE) NULL );
  754.  
  755.     TF = create_tmpfile();
  756.  
  757.     TF->tid = tid;
  758.  
  759.     if ( index > 1 )
  760.         sprintf( fname, "%s/tmp.%x.%d", DIRNAME, tid, index );
  761.  
  762.     else
  763.         sprintf( fname, "%s/tmp.%x", DIRNAME, tid );
  764.  
  765.     TF->fname = trc_copy_str( fname );
  766.  
  767.     if ( !verify_fp( TF, "w" ) )
  768.     {
  769.         free( TF );
  770.         return( (TMPFILE) NULL );
  771.     }
  772.  
  773.     if ( index > 1 )
  774.     {
  775.         TF->delta.tv_sec = delta.tv_sec;
  776.         TF->delta.tv_usec = delta.tv_usec;
  777.     }
  778.  
  779.     TF->next = TMPF;
  780.  
  781.     TMPF = TF;
  782.  
  783.     return( TF );
  784. }
  785.  
  786.  
  787. void
  788. get_tevrec_tmpfile( TF )
  789. TMPFILE TF;
  790. {
  791.     FILE *savefp;
  792.  
  793.     if ( TF->eof )
  794.         return;
  795.  
  796.     CURRENTTF = TF;
  797.  
  798.     if ( !verify_fp( TF, "r" ) )
  799.         bail();
  800.  
  801.     savefp = ID->trace_in;
  802.  
  803.     ID->trace_in = TF->fpbuf->fp;
  804.  
  805.     trc_read_trace_event( ID, &(TF->eof) );
  806.  
  807.     ID->trace_in = savefp;
  808. }
  809.  
  810.  
  811. void
  812. sync_time( TF )
  813. TMPFILE TF;
  814. {
  815.     TF->nexttime.tv_sec += TF->delta.tv_sec;
  816.     TF->nexttime.tv_usec += TF->delta.tv_usec;
  817.  
  818.     if ( TF->nexttime.tv_usec > 1000000 )
  819.     {
  820.         TF->nexttime.tv_usec -= 1000000;
  821.  
  822.         (TF->nexttime.tv_sec)++;
  823.     }
  824.  
  825.     else if ( TF->nexttime.tv_usec < 0 )
  826.     {
  827.         TF->nexttime.tv_usec += 1000000;
  828.  
  829.         (TF->nexttime.tv_sec)--;
  830.     }
  831. }
  832.  
  833.  
  834. /* FPBUF Routines */
  835.  
  836. FPBUF
  837. create_fpbuf()
  838. {
  839.     FPBUF tmp;
  840.  
  841.     tmp = (FPBUF) malloc( sizeof( struct fp_buffer_struct ) );
  842.     trc_memcheck( tmp, "File Buffer Structure" );
  843.  
  844.     tmp->fp = (FILE *) NULL;
  845.  
  846.     tmp->rwstr = (char *) NULL;
  847.  
  848.     tmp->tmpfile = (TMPFILE) NULL;
  849.  
  850.     tmp->next = (FPBUF) NULL;
  851.  
  852.     if ( vflag )
  853.         { printf( "+" ); fflush( stdout ); }
  854.  
  855.     return( tmp );
  856. }
  857.  
  858.  
  859. void
  860. free_fpbuf( ptr )
  861. FPBUF *ptr;
  862. {
  863.     FPBUF FPB;
  864.  
  865.     if ( ptr == NULL || *ptr == NULL )
  866.         return;
  867.     
  868.     FPB = *ptr;
  869.  
  870.     /* Close Any Open File Ptr */
  871.  
  872.     if ( FPB->fp != NULL )
  873.     {
  874.         if ( FPB->tmpfile != NULL )
  875.             FPB->tmpfile->lastseek = ftell( FPB->fp );
  876.  
  877.         fclose( FPB->fp );
  878.  
  879.         FPB->fp = (FILE *) NULL;
  880.     }
  881.  
  882.     FPB->rwstr = (char *) NULL;
  883.  
  884.     if ( FPB->tmpfile != NULL )
  885.     {
  886.         FPB->tmpfile->fpbuf = (FPBUF) NULL;
  887.  
  888.         FPB->tmpfile = (TMPFILE) NULL;
  889.     }
  890.  
  891.     FPB->next = (FPBUF) NULL;
  892.  
  893.     free( FPB );
  894.  
  895.     *ptr = (FPBUF) NULL;
  896.  
  897.     if ( vflag )
  898.         { printf( "\b \b" ); fflush( stdout ); }
  899. }
  900.  
  901.  
  902. int
  903. verify_fp( TF, rwstr )
  904. TMPFILE TF;
  905. char *rwstr;
  906. {
  907.     FPBUF FPBlast;
  908.     FPBUF FPBptr;
  909.     FPBUF FPB;
  910.  
  911.     /* File Ptr Buffer Already There */
  912.  
  913.     if ( TF->fpbuf )
  914.     {
  915.         /* Verify Same Mode */
  916.  
  917.         if ( !strcmp( TF->fpbuf->rwstr, rwstr ) )
  918.         {
  919.             /* Move to Top of List */
  920.  
  921.             if ( FPS != TF->fpbuf )
  922.             {
  923.                 if ( FPS == NULL )
  924.                 {
  925.                     printf( "Warning:  Empty File Ptr Buffer List\n" );
  926.  
  927.                     return( TRC_TRUE );
  928.                 }
  929.  
  930.                 FPB = FPS;
  931.  
  932.                 while ( FPB->next != NULL )
  933.                 {
  934.                     if ( FPB->next == TF->fpbuf )
  935.                     {
  936.                         FPB->next = TF->fpbuf->next;
  937.  
  938.                         TF->fpbuf->next = FPS;
  939.  
  940.                         FPS = TF->fpbuf;
  941.  
  942.                         return( TRC_TRUE );
  943.                     }
  944.  
  945.                     FPB = FPB->next;
  946.                 }
  947.  
  948.                 printf(
  949.                     "Warning:  Verify File Ptr Buffer Not Found\n" );
  950.             }
  951.  
  952.             return( TRC_TRUE );
  953.         }
  954.  
  955.         /* Switching File Modes, Close File Ptr */
  956.  
  957.         else
  958.             close_fp( TF );
  959.     }
  960.  
  961.     /* Check for Flush */
  962.  
  963.     if ( NFPS >= MAX_OPEN_FP )
  964.     {
  965.         FPBptr = FPS;
  966.  
  967.         FPBlast = (FPBUF) NULL;
  968.  
  969.         while ( FPBptr->next != NULL )
  970.         {
  971.             FPBlast = FPBptr;
  972.             FPBptr = FPBptr->next;
  973.         }
  974.  
  975.         if ( FPBlast != NULL )
  976.             free_fpbuf( &(FPBlast->next) );
  977.  
  978.         else
  979.             free_fpbuf( &(FPS) );
  980.  
  981.         NFPS--;
  982.     }
  983.  
  984.     /* Create New File Ptr Buffer */
  985.  
  986.     FPB = create_fpbuf();
  987.  
  988.     FPB->fp = fopen( TF->fname, rwstr );
  989.  
  990.     if ( !trc_filecheck( FPB->fp, TF->fname ) )
  991.     {
  992.         free_fpbuf( &FPB );
  993.  
  994.         return( TRC_FALSE );
  995.     }
  996.  
  997.     else
  998.     {
  999.         /* Add File Ptr Buffer to List */
  1000.  
  1001.         FPB->rwstr = rwstr;
  1002.  
  1003.         FPB->tmpfile = TF;
  1004.         TF->fpbuf = FPB;
  1005.  
  1006.         FPB->next = FPS;
  1007.         FPS = FPB;
  1008.  
  1009.         NFPS++;
  1010.  
  1011.         /* Check for File Seek */
  1012.  
  1013.         if ( TF->lastseek != 0 )
  1014.         {
  1015.             if ( fseek( FPB->fp, TF->lastseek, 0 ) )
  1016.             {
  1017.                 printf( "\nError in fseek() of Temp File\n\n" );
  1018.                 bail();
  1019.             }
  1020.         }
  1021.  
  1022.         /* Success */
  1023.  
  1024.         return( TRC_TRUE );
  1025.     }
  1026. }
  1027.  
  1028.  
  1029. void
  1030. close_fp( TF )
  1031. TMPFILE TF;
  1032. {
  1033.     FPBUF FPBlast;
  1034.     FPBUF FPB;
  1035.  
  1036.     int flag;
  1037.  
  1038.     /* Check for Null File Ptr Buffer */
  1039.  
  1040.     if ( TF->fpbuf == NULL )
  1041.     {
  1042.         TF->lastseek = (long) 0;
  1043.  
  1044.         return;
  1045.     }
  1046.  
  1047.     /* Remove Buffer From List */
  1048.  
  1049.     if ( FPS != NULL )
  1050.     {
  1051.         if ( FPS == TF->fpbuf )
  1052.         {
  1053.             FPS = TF->fpbuf->next;
  1054.  
  1055.             NFPS--;
  1056.         }
  1057.  
  1058.         else
  1059.         {
  1060.             FPB = FPS;
  1061.  
  1062.             flag = 0;
  1063.  
  1064.             while ( FPB->next != NULL && !flag )
  1065.             {
  1066.                 if ( FPB->next == TF->fpbuf )
  1067.                 {
  1068.                     FPB->next = TF->fpbuf->next;
  1069.  
  1070.                     NFPS--;
  1071.  
  1072.                     flag++;
  1073.                 }
  1074.  
  1075.                 else
  1076.                     FPB = FPB->next;
  1077.             }
  1078.  
  1079.             if ( !flag )
  1080.             {
  1081.                 printf(
  1082.                     "Warning:  Close File Ptr Buffer Not Found.\n" );
  1083.             }
  1084.         }
  1085.     }
  1086.  
  1087.     free_fpbuf( &(TF->fpbuf) );
  1088.  
  1089.     TF->lastseek = (long) 0;
  1090. }
  1091.  
  1092.  
  1093. /* Clean Up Temp Directory */
  1094.  
  1095. void
  1096. cleanup()
  1097. {
  1098.     TMPFILE TF;
  1099.  
  1100.     TF = TMPF;
  1101.  
  1102.     while ( TF != NULL )
  1103.     {
  1104.         if ( TF->fname != NULL )
  1105.             unlink( TF->fname );
  1106.  
  1107.         TF = TF->next;
  1108.     }
  1109.  
  1110.     unlink( DIRNAME );
  1111. }
  1112.  
  1113.  
  1114. void
  1115. bail()
  1116. {
  1117.     cleanup();
  1118.  
  1119.     exit( -1 );
  1120. }
  1121.  
  1122.